﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using PostSharp.Laos;

using MCromwell.StaffIntranet.Task.Infrastructure.Logging;
using MCromwell.StaffIntranet.DependencyInjection;
using MCromwell.StaffIntranet.Task.Extensions;


namespace MCromwell.StaffIntranet.Task.Infrastructure
{
    [Serializable]
    [AttributeUsage(AttributeTargets.All)]
    public class TaskExceptionHandlerAttribute : OnMethodBoundaryAspect
    {
        public override void OnException(MethodExecutionEventArgs eventArgs)
        {
            Exception thrownException = eventArgs.Exception;

            LogException(thrownException);

            WrapExceptionWithAttribute wrapExceptionAttribute = RetrieveWrappingExceptionAttribute(eventArgs.Method);
            if (wrapExceptionAttribute != null)
            {
                Type exceptionToWrapWith = wrapExceptionAttribute.WrapExceptionType;
                Exception exceptionToThrow = (Exception)Activator.CreateInstance(exceptionToWrapWith, thrownException);
                if (exceptionToThrow != null)
                    throw exceptionToThrow;
            }
            throw new TaskLayerException(thrownException);   
        }

        private static WrapExceptionWithAttribute RetrieveWrappingExceptionAttribute(MethodBase method)
        {
            WrapExceptionWithAttribute wrapExceptionAttribute =
                        method.GetFirstCustomAttribute<WrapExceptionWithAttribute>(typeof(WrapExceptionWithAttribute),
                                                                                              false);
            return wrapExceptionAttribute;
        }

        private static void LogException(Exception thrownException)
        {
            ILog log = IoC.Resolve<ILog>();
            log.Error(thrownException);
        }

    }
     
}
